package com.gpt.article.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import chatgpt.ChatGPT;
import chatgpt.entity.chat.ChatCompletion;
import chatgpt.entity.chat.ChatCompletionResponse;
import chatgpt.entity.chat.Message;
import com.alibaba.fastjson.JSON;
import com.gpt.article.controller.websocket.WebSocketUsers;
import com.gpt.article.domain.*;
import com.gpt.article.mapper.AContentMapper;
import com.gpt.article.service.impl.taskHandle.GenQContentTask;
import com.gpt.article.service.impl.taskHandle.GenTask;
import com.gpt.article.service.impl.taskHandle.GenTopicArticleTask;
import com.gpt.article.service.impl.taskHandle.GptRequstHelper;
import com.gpt.article.service.impl.taskHandle.task.GenQContentTasker;
import com.gpt.article.service.impl.taskHandle.task.XiGaoTasker;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDictTypeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.gpt.article.mapper.QContentMapper;
import com.gpt.article.service.IQContentService;
import org.springframework.util.ObjectUtils;

/**
 * 模型比较Service业务层处理
 * 
 * @author zhuzi
 * @date 2024-02-25
 */
@Service
public class QContentServiceImpl implements IQContentService 
{
    private static Logger logger = LoggerFactory.getLogger(QContentServiceImpl.class);

    private static Integer a_content_num = 0;
    @Autowired
    private QContentMapper qContentMapper;

    @Autowired
    AContentMapper aContentMapper;
    @Autowired
    private GptGenArticleTaskServiceImpl gptGenArticleTaskServiceImpl;

    @Autowired
    private  GptFunPromptsServiceImpl   gptFunPromptsServiceImpl;

    @Autowired
    private  ISysDictTypeService sysDictTypeService;
    public static Integer getA_content_num() {
        return a_content_num;
    }

    public static void setA_content_num(Integer a_content_num) {
        QContentServiceImpl.a_content_num = a_content_num;
    }

    /**
     * 查询模型比较
     * 
     * @param id 模型比较主键
     * @return 模型比较
     */
    @Override
    public QContent selectQContentById(Long id)
    {
        return qContentMapper.selectQContentById(id);
    }

    /**
     * 查询模型比较列表
     * 
     * @param qContent 模型比较
     * @return 模型比较
     */
    @Override
    public List<QContent> selectQContentList(QContent qContent)
    {
        //处理集合中多余的空对象
        List<QContent> qContents = qContentMapper.selectQContentList(qContent);
        List<AContent> acontentList = aContentMapper.selectAContentList(new AContent());

//        AContent aContent = null;
        List<AContent> aContentList = null;
        List<Map<String, List<AContent>>> aContentMapList = null;

        loop1:for(QContent qContent1:qContents){
            aContentList = new ArrayList<AContent>();
            loop2:for(AContent aContent:acontentList){
                if(aContent.getqContentId().equals(qContent1.getId())){
                    aContentList.add(aContent);
//                    break loop2;
                }
            }


            //将aContentList 根据ModelCode 分组 形成Map<String, List<AContent>> 结构
            Map<String, List<AContent>> groupedMap = aContentList.stream()
                    .collect(Collectors.groupingBy(AContent::getModelCode));



//           groupedMap.entrySet().stream()
//                    .sorted(Map.Entry.comparingByKey())
//                    .forEachOrdered(e -> {
//                        e.getValue().sort(Comparator.comparing(AContent::getCreateTime));
//                        groupedMap.put(e.getKey(), e.getValue());
//                    });

            qContent1.setaContents(aContentList);
            qContent1.setMapAcontentByModel(groupedMap);
        }
        return qContents;
    }

    /**
     * 新增模型比较
     * 
     * @param qContent 模型比较
     * @return 结果
     */
    @Override
    public Long insertQContent(QContent qContent)
    {
        qContent.setCreateTime(DateUtils.getNowDate());
        qContent.setUpdateTime(DateUtils.getNowDate());
        qContentMapper.insertQContent(qContent);
        return qContent.getFileId();
    }


    /**
     * 修改模型比较
     * 
     * @param qContent 模型比较
     * @return 结果
     */
    @Override
    public int updateQContent(QContent qContent)
    {
        qContent.setUpdateTime(DateUtils.getNowDate());
        return qContentMapper.updateQContent(qContent);
    }

    /**
     * 批量删除模型比较
     * 
     * @param ids 需要删除的模型比较主键
     * @return 结果
     */
    @Override
    public int deleteQContentByIds(Long[] ids)
    {
        aContentMapper.deleteAContentBycontentIds(ids);
        return qContentMapper.deleteQContentByIds(ids);

    }

    /**
     * 删除模型比较信息
     * 
     * @param id 模型比较主键
     * @return 结果
     */
    @Override
    public int deleteQContentById(Long id)
    {
        return qContentMapper.deleteQContentById(id);
    }


    @Override
    public int genGptContent(Long[] ids, String acc, Map<String,Object> map) {
        List<QContent> qContents = qContentMapper.selectQContentListByIds(ids);
        String useModels = String.valueOf(map.get("usemodelCode"));
        useModels = useModels.replaceAll("\\[","").replaceAll("\\]","").replaceAll(" ","").trim();
        if(StringUtils.isNotEmpty(useModels)){
            for(QContent qContent:qContents){
                qContent.setModelCodes(useModels);
//                qContentMapper.updateQContent(qContent);
            }
        }

        Integer xigaoAllNum = genStart(qContents,acc);
        System.out.println("本批次任务数：："+qContents.size());

        return 0;
    }

    @Override
    public int genContentOne(List<String> usemodelCodes, String prompts_input, String acc) {
        QContent qContent = new QContent();
        String models = String.join(",", usemodelCodes);
        qContent.setPrompts(prompts_input);
        qContent.setModelCodes(models);
        qContent.setGenStatus("1");
        qContent.setGennum(usemodelCodes.size());
        qContent.setCreateTime(DateUtils.getNowDate());
        Long id = insertQContent(qContent);
        List<QContent> qContents = new ArrayList<QContent>();
        qContent.setId(id);
        qContents.add(qContent);
        genStart(qContents,acc);
        return 0;
    }

    @Override
    public int genManyContent(QContent qContent, String acc, Map<String,Object> map) {
        List<QContent> qContents = new ArrayList<QContent>();
        boolean findAll = false;
        Integer taskSum = qContentMapper.getQContentCount(qContent);
        if(qContent.getGennum()==0){
            findAll = true;
        }
        if(!findAll){
            taskSum = taskSum>qContent.getGennum()?qContent.getGennum():taskSum;
        }
        qContents = qContentMapper.selectQContentIdsList(qContent);
        if(qContents.size()==0){
            try {
                throw new Exception("没有找到符合条件的问题");
            }catch (Exception e) {
                e.printStackTrace();
            }
        }


        String useModels = String.valueOf(map.get("usemodelCode"));
        useModels = useModels.replaceAll("\\[","").replaceAll("\\]","").replaceAll(" ","").trim();
        if(StringUtils.isNotEmpty(useModels)){
            for(QContent qc:qContents){
                qc.setModelCodes(useModels);
            }
        }

        genStart(qContents,acc);
        return 0;
    }

    @Override
    public int genAddPrompts(Map<String, Object> map,String acc) {

        Long qcontentid =Long.valueOf(String.valueOf(map.get("qcontentid"))) ;

        String prompts = String.valueOf(map.get("prompts"));
        String usemodelCode = String.valueOf(map.get("usemodelCode"));

        String acid = String.valueOf(map.get("acontentid"));
        Boolean isOne = false;
        if(StringUtils.isNotEmpty(acid)&&!"null".equals(acid)){
            isOne = true;
        }else{
            isOne = false;
        }
        new GenQContentTasker().resetExcu();
        QContent qContent = qContentMapper.selectQContentById(qcontentid);;
        //单条
        if(isOne){
            Long acontentid = Long.valueOf(String.valueOf(map.get("acontentid")));
            AContent aContent = aContentMapper.selectAContentById(acontentid);
            usemodelCode = aContent.getModelCode();
        }else{
            //批量对该回答下所有模型
            usemodelCode =  qContent.getModelCodes();
        }
        GptFunPrompts gptFunPrompts =  gptFunPromptsServiceImpl.selectGptFunPromptsByName("chat-comparer");
        String models[] = usemodelCode.split(",");
        List<AContent> aContentList = new ArrayList<AContent>();
        if(isOne){
            Long acontentid = Long.valueOf(String.valueOf(map.get("acontentid")));
            AContent ac = aContentMapper.selectAContentById(acontentid);
            aContentList.add(ac);
        }else{
            AContent psaContent = new AContent();
            psaContent.setqContentId(qcontentid);
            aContentList = aContentMapper.selectAContentList(psaContent);
        }

        Message user = new Message();
        Message asst = new Message();
        List messagesList  = new ArrayList();
        user = Message.of(qContent.getPrompts());
        messagesList.add(user);
        List<SysDictData> dictModellist = sysDictTypeService.selectDictDataByType("gpt_model");


        //任务数量
        int taskNum = models.length;

        String jsonString = seedTxt(taskNum,taskNum,"start");
        WebSocketUsers.sendMessageToUsersByText(jsonString);


        //创建任务
        GptGenArticleTask genArticleTask = new  GptGenArticleTask();
        genArticleTask.setProce(0);
        genArticleTask.setArticleNum(taskNum);
        genArticleTask.setStatus("1");
        genArticleTask.setSuccessNum(0);
        genArticleTask.setErrorNum(0);
        genArticleTask.setCreateTime(DateUtils.getNowDate());
        Long taskId =gptGenArticleTaskServiceImpl.insertGptGenArticleTask(genArticleTask);

        ChatGPT chatGPT = null;
        try {
            chatGPT = ChatGPT.builder()
                    .apiKey(RuoYiConfig.getApiKeys())
                    .timeout(9000)
//                .proxy(proxy)
                    .apiHost(RuoYiConfig.getGptApiHost()) //代理地址
                    .build()
                    .init();
        }catch (Exception e){
            logger.error("丢包或者请求异常重试:{}",e.getMessage());
            chatGPT = new GptRequstHelper().getGpt(chatGPT);
        }
        ChatCompletion chatCompletion = null;

        int codenum = taskNum;
        int successNum = 0;
        int errorNum = 0;
        for(String modeCode:models){

            //加载历史消息
            for(AContent aContent:aContentList){
                if(aContent.getModelCode().equals(modeCode)){
                    user =new Message();
                    asst = new Message();
                    //获取回答
                    if("0".equals(aContent.getQpType())){
                        asst = Message.ofAssistant(aContent.getaContent());
                        messagesList.add(asst);
                    }
                    if("1".equals(aContent.getQpType())){
                        user = Message.of(aContent.getaContent());
                        messagesList.add(user);
                    }
                }
            }

            //提问最新消息
            Message newuser = new Message();
            newuser = Message.of(prompts);


            Message systEmRole = null;
            String system = gptFunPrompts.getSystemRole();
            if(!"null".equals(system)&&!StringUtils.isEmpty(system)){
                systEmRole = Message.ofSystem(system);
                messagesList.add(systEmRole);
            }
            messagesList.add(newuser);
            chatCompletion = ChatCompletion.builder()
                    .model(modeCode)
                    .messages(messagesList)
//                    .maxTokens(2000)
//                    .temperature(0.5)
//                    .topP(1.0)
                    .maxTokens(gptFunPrompts.getMaxTokens())
                    .temperature(gptFunPrompts.getTemperature())
                    .topP(gptFunPrompts.getTopP())
                    .presencePenalty(gptFunPrompts.getPresencePenalty())
                    .frequencyPenalty(gptFunPrompts.getFrequencyPenalty())

                    .build();
//            gptFunPrompts

            logger.info("任务生成中...");
            long startTime = System.currentTimeMillis();
            ChatCompletionResponse response = null;
            try {
                response = chatGPT.chatCompletion(chatCompletion);
            }catch (Exception e){
                map.put("status","3");
                errorNum+=1;
                logger.error("生成出错：：：使用模型：："+modeCode+",prompts:"+prompts+",,emsg::"+e.getMessage());
                continue;
            }

            long endTime = System.currentTimeMillis();
            long elapsedTime = endTime - startTime;
            logger.info("生成任务完成！耗时：{}",elapsedTime);

            if(ObjectUtils.isEmpty(response.getUsage())){
                //重试一次
                logger.error("任务生成失败，,,请检查余额或者模型是否正确");
                logger.error("生成出错：：：使用模型：："+modeCode+",prompts:"+prompts);
                errorNum+=1;
                continue;
            }

            codenum-=1;
            String msgString = seedTxt(taskNum,codenum,"start");
            WebSocketUsers.sendMessageToUsersByText(msgString);


            Message res = response.getChoices().get(0).getMessage();
            String acontent = res.getContent();
            logger.info("使用模型：{}",modeCode+",其中prompts:"+prompts);
            logger.info("回答：{}",acontent);


            int thisModelTokenCount = 0;
            try {
                thisModelTokenCount = Integer.valueOf(String.valueOf(response.getUsage().getTotalTokens()));
            }catch (Exception e){
                logger.error("获取token数量失败:{}",e.getMessage());
            }

            String modelName = "";

            for(SysDictData dict:dictModellist){
                if(dict.getDictValue().equals(modeCode)){
                    modelName = dict.getDictLabel();
                }
            }

            //插入问题
            AContent insertQAcontent = new AContent();
            insertQAcontent.setqContentId(qcontentid);
            insertQAcontent.setaContent(prompts);
            if(StringUtils.isEmpty(acontent)){
                insertQAcontent.setStatus("3");
            }else {
                insertQAcontent.setStatus("2");
            }
            insertQAcontent.setQpType("1");
            insertQAcontent.setModelCode(modeCode);
            insertQAcontent.setModelName(modelName);
            insertQAcontent.setUseToken(thisModelTokenCount);
            insertQAcontent.setCreateBy(acc);
            aContentMapper.insertAContent(insertQAcontent);


            //插入回答
            AContent insertAAcontent = new AContent();
            insertAAcontent.setqContentId(qcontentid);
            if(StringUtils.isEmpty(acontent)){
                insertAAcontent.setaContent(null);
                insertAAcontent.setStatus("3");
                errorNum+=1;
            }else {
                insertAAcontent.setaContent(acontent);
                insertAAcontent.setStatus("2");
                successNum+=1;
            }
            insertAAcontent.setQpType("0");
            insertAAcontent.setModelCode(modeCode);
            insertAAcontent.setModelName(modelName);
            insertAAcontent.setUseToken(thisModelTokenCount);
            insertAAcontent.setCreateBy(acc);
            aContentMapper.insertAContent(insertAAcontent);

            if((successNum+errorNum)==taskNum){
                new XiGaoTasker().upTask(taskId,successNum,errorNum,(successNum+errorNum),"3");
            }else{
                new XiGaoTasker().upTask(taskId,successNum,errorNum,(successNum+errorNum),"2");
            }


        }
        String msgString = seedTxt(taskNum,0,"end");
        WebSocketUsers.sendMessageToUsersByText(msgString);
        return taskNum;
    }


    /**
     * 发送消息
     * @param taskNum
     * @return
     */
        public String seedTxt(Integer taskNum,Integer syNum,String statusstr){
            String  message = "任务提示:\n 当前需生成：生成的回答"+taskNum+"个\n"
                    +"剩余任务：剩余回答"+(syNum)+"个\n"+
                    "当前任务：等待模型生成中...";
            Integer percentage = 0;

            Map<String,Object> msgmap = new HashMap<String,Object>();
            msgmap.put("message",message);
            msgmap.put("percentage",percentage);
            msgmap.put("status",statusstr);
            msgmap.put("acontentId",null);
            String  jsonString = JSON.toJSONString(msgmap);
            return  jsonString;
        }

    /**
     * 创建任务
     * @param qContents
     * @return
     */
    public Integer genStart(List<QContent> qContents,String acc ){
        GptGenArticleTask genArticleTask = new  GptGenArticleTask();
        genArticleTask.setProce(0);
        genArticleTask.setArticleNum(qContents.size());
        genArticleTask.setStatus("1");
        genArticleTask.setSuccessNum(0);
        genArticleTask.setErrorNum(0);
        genArticleTask.setCreateTime(DateUtils.getNowDate());
        Long taskId =gptGenArticleTaskServiceImpl.insertGptGenArticleTask(genArticleTask);
        GptFunPrompts gptFunPrompts =  gptFunPromptsServiceImpl.selectGptFunPromptsByName("chat-comparer");

        //开启任务
        Integer xigaoAllNum = new GenQContentTask().createQContentTask(taskId,acc,qContents,gptFunPrompts);

        return qContents.size();
    }




}
